// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: linchuan

#pragma once

#include <cstdio>
#include <memory>
#include <set>
#include <string>

#include <rapidjson/document.h>

#include "coin2/exchange/base/order/order.h"
#include "coin2/exchange/huobi/symbology/currency.h"
#include "coin2/exchange/huobi/symbology/product.h"

namespace coin2::exchange::huobi::order_v1 {

class HuobiParser : public base::order::BaseParser {
 public:
  const ParseResult& ParseRawMessage(const RawMessage& msg) override;
  AccountBalance ParseBalance(const JsonValue& doc) override;
  bool ParseRawBalance(const JsonValue& doc, RawBalanceMap* raw_balance_map);
  CurrencyTransferBundle ParseTransfer(const JsonValue& doc);
  bool ParseRawMarginBalance(const JsonValue& doc, RawBalanceMap* raw_balance_map);

 private:
  void ParseSubmitResponse();
  void ParseBatchSubmitResponse();
  void ParseCancelResponse();
  void ParseBatchCancelResponse();
  void ParseRestOrdersInfo();
  void ParseRestFillInfoList();
  void ParseRestDeposit();
  void ParseRestWithdrawal();
  void ParseRestSpotAccountBalance();
  void ParseRestMarginCrossedAccountBalance();
  void ParseRestMarginIsolatedAccountBalance();
  void ParseWsMessage();
  void ParseRestAccounts();
  void ParseRestTransfers(const std::string& id);

  std::map<std::string, std::string> ParseAccountTypeIdMap(const JsonValue& doc);
  coin::proto::ProductOrderElement ParseRestOrderInfo(const JsonValue& data);
  bool ParseWsOrderInfo(const JsonValue& data, coin::proto::ProductOrderElement* order);
  ProductOrderBundle ParseWsOrderInfoListV2(const JsonValue& data);
  ProductFillBundle ParseWsFillInfoListV2(const JsonValue& data);
  void MergeMarginAccountBalance(AccountBalance* acc_balance);

 private:
  bool is_account_balance_initialized_ = false;
  bool is_crossed_margin_balance_initialized = false;
  bool is_isolated_margin_balance_initialized = false;
  RawBalanceMap crossed_margin_balance_map_cache_;
  RawBalanceMap isolated_margin_balance_map_cache_;
  std::map<std::string, std::string> transfer_deposit_map_;
  bool is_transfer_deposit_initialized_ = false;
  std::map<std::string, std::string> transfer_withdrawal_map_;
  bool is_transfer_withdrawal_initialized_ = false;

  std::map<std::string, std::string> transfer_subaccount_map_;
  std::set<std::string> transfer_subaccount_initialized_set_;
};

}  // namespace coin2::exchange::huobi::order_v1
